package de.preamp.clients.java.utils;

import java.awt.Image;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import javax.swing.ImageIcon;

import net.roarsoftware.lastfm.ImageSize;

/**
 * This is a proxy class to last.fm. Images for artists an album covers are
 * cached so they won't have to be loaded from last.fm each time.<br>
 * 
 * @author André Stannek
 * @version 2010-03-21
 */
public final class ImageCache
{

    /**
     * Generated UID.
     */
    private static final long serialVersionUID = 89424481167908699L;

    /**
     * A map holding an image for each artist identified by his name as key.
     */
    private final transient Map<String, ImageIcon> images;

    /**
     * The map holding the covers with a String as key. The String is the artist
     * and album name concatinated.
     */
    private final transient Map<String, ImageIcon> covers;

    /**
     * The singleton Object of this class.
     */
    private static transient ImageCache cacheInstance;

    /**
     * Tries to get an Image for an artist from cache. If the cache does not
     * contain one it is loaded from last.fm. If no image is found last.fm a
     * generic audio image will be returned. Width or height of the image has a
     * maximum of 100. The shorter side of the image will be scaled to that.<br>
     * For performance reasons this method does not save the new cache to a
     * file. Call the {@link ImageCache#save()} method to do this.
     * 
     * @param artist
     *            the artist
     * @return an image for the artist
     */
    public static ImageIcon getArtistImage(final String artist)
    {
	final ImageCache cache = ImageCache.instance();
	ImageIcon image;
	ImageIcon scaledImage;
	if (cache.images.containsKey(artist))
	{
	    scaledImage = cache.images.get(artist);
	}
	else
	{
	    try
	    {
		final net.roarsoftware.lastfm.Artist lfmArtist =
			net.roarsoftware.lastfm.Artist.getInfo(artist,
				AbstractPreferences.LASTFM_API_KEY);
		final String imageURL = lfmArtist.getImageURL(ImageSize.LARGE);

		image = new ImageIcon(new URL(imageURL));

		final int height = image.getIconHeight();
		final int width = image.getIconWidth();
		final int ratio = height / width;
		if (height > width)
		{
		    scaledImage =
			    new ImageIcon(image.getImage().getScaledInstance(
				    100 / ratio, 100, Image.SCALE_FAST));
		}
		else
		{
		    scaledImage =
			    new ImageIcon(image.getImage().getScaledInstance(
				    100, 100 * ratio, Image.SCALE_FAST));
		}

		cache.images.put(artist, scaledImage);
	    }
	    catch (final MalformedURLException e1)
	    {
		scaledImage =
			new ImageIcon(ImageLoader
				.getImageURL("audio-x-generic.png"));
	    }
	}
	return scaledImage;
    }

    /**
     * Tries to get a Cover, scaled to a size of 100x100, for an album,
     * identified by artist an album name, from cache. If the cache does not
     * contain one it is loaded from last.fm. If no cover is found last.fm a
     * generic audio image will be returned. <br>
     * For performance reasons this method does not save the new cache to a
     * file. Call the {@link ImageCache#save()} method to do this.
     * 
     * @param artist
     *            the artist name
     * @param album
     *            the album title
     * @return the Image
     */
    public static ImageIcon getCover(final String artist, final String album)
    {
	final ImageCache cache = ImageCache.instance();
	final ImageIcon cover;
	ImageIcon scaledImage;
	final String dbID = artist + album;
	if (cache.covers.containsKey(dbID))
	{
	    scaledImage = cache.covers.get(dbID);
	}
	else
	{
	    try
	    {
		final net.roarsoftware.lastfm.Album lfmAlbum =
			net.roarsoftware.lastfm.Album.getInfo(artist, album,
				AbstractPreferences.LASTFM_API_KEY);
		final String imageURL = lfmAlbum.getImageURL(ImageSize.LARGE);

		cover = new ImageIcon(new URL(imageURL));
		scaledImage =
			new ImageIcon(cover.getImage().getScaledInstance(100,
				100, Image.SCALE_FAST));
		cache.covers.put(dbID, scaledImage);
	    }
	    catch (final MalformedURLException e)
	    {
		scaledImage =
			new ImageIcon(ImageLoader
				.getImageURL("audio-x-generic.png"));
	    }
	}
	return scaledImage;
    }

    /**
     * @return a {@link Map} of all images for artists with the artist name as
     *         key
     */
    public Map<String, ImageIcon> getArtistImages()
    {
	return images;
    }

    /**
     * @return a singleton instance of {@link ImageCache}
     */
    public static ImageCache instance()
    {
	final Object lock = new Object();
	synchronized (lock)
	{
	    if (cacheInstance == null)
	    {
		final ImageCache temp = new ImageCache();
		cacheInstance = temp;
	    }
	    return cacheInstance;
	}
    }

    /**
     * Private Constructor for singleton pattern.
     */
    private ImageCache()
    {
	images = new HashMap<String, ImageIcon>();
	covers = new HashMap<String, ImageIcon>();
    }
}
